package com.xishu.service;

import com.xishu.entity.AbstractEntity;
import com.xishu.entity.NameAndId;
import com.xishu.entity.hardware.PrinterLabel;
import com.xishu.entity.shop.*;
import com.xishu.response.ResponseStatus;
import com.xishu.response.VerifyUtil;
import com.xishu.service.order.base.OrderService;
import com.xishu.util.ClassUtil;
import com.xishu.util.Tools;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

public class ImportService implements Tools {
    private static ImportService instance = new ImportService();
    private static Logger logger = LoggerFactory.getLogger(ImportService.class);
    private CommonService commonService = CommonService.getInstance();
    private ShopService shopService = ShopService.getInstance();

    private ImportService() {
    }

    public static ImportService getInstance() {
        return instance;
    }

    /**
     * 导入场景
     *
     * @param srcShopId
     * @param desShopId
     */
    public void importScene(Long srcShopId, Long desShopId) throws Exception {
        List<Scene> sceneList = ShopService.getInstance().findSceneList(srcShopId);

        if (commonService.isEmpty(sceneList)) {
            logger.info("src shop id {} scene is empty", srcShopId);
            return;
        }

        Shop shop = ShopService.getInstance().findShopById(desShopId);

        for (Scene srcScene : sceneList) {
            Scene desScene = new Scene();
            BeanUtils.copyProperties(srcScene, desScene);
            desScene.setShopId(desShopId);
            desScene.setId(null);
            desScene.setFoodTableConfigId(null);
            desScene.setShopName(shop.getName());

            //如果有餐桌配置，那么重新设置餐桌配置
            if (srcScene.getFoodTableConfigId() != null) {
                Long srcFoodTableConfigId = srcScene.getFoodTableConfigId();
                Optional<FoodTableConfig> foodTableConfigOptional = commonService.searchOneOptional(srcFoodTableConfigId, FoodTableConfig.class);

                if (!foodTableConfigOptional.isPresent()) {
                    logger.info("the food table config deleted");
                    commonService.createObject(desScene, null, false, null);
                    continue;
                }

                FoodTableConfig foodTableConfig = foodTableConfigOptional.get();

                Integer showIndex = foodTableConfig.getShowIndex();

                if (showIndex != null) {
                    Optional<FoodTableConfig> foodTableConfigByName = findFoodTableConfigByName(showIndex, desShopId);
                    if (foodTableConfigByName.isPresent()) {
                        logger.info("find the food table config is {}", foodTableConfigByName.get());
                        FoodTableConfig desFoodTableConfig = foodTableConfigByName.get();
                        desScene.setFoodTableConfigId(desFoodTableConfig.getId());
                        desScene.setFoodTableConfigIndex(desFoodTableConfig.getShowIndex());
                    } else {
                        logger.info("can not find the table config {}", showIndex);
                    }
                }
            }

            commonService.createObject(desScene, null, false, null);
             //清空缓存，刷新缓存
            SceneService.getInstance().putCache(desScene.getShopId());
            //同步餐桌配置到场景
            if (desScene.getFoodTableConfigId() != null) {
                Optional<FoodTableConfig> foodTableConfigOptional = commonService.searchOneOptional(desScene.getFoodTableConfigId(), FoodTableConfig.class);
                if (foodTableConfigOptional.isPresent()) {
                    FoodTableConfig foodTableConfig = foodTableConfigOptional.get();
                    FoodTableService.getInstance().syncFoodTableConfigToScene(foodTableConfig, desScene.getId());
                }
            }
        }

    }

    /**
     * 在一个分店里面查询餐桌配置
     *
     * @param showIndex
     * @param shopId
     * @return
     */
    public Optional<FoodTableConfig> findFoodTableConfigByName(Integer showIndex, Long shopId) {
        FoodTableConfig foodTableConfig = new FoodTableConfig();
        foodTableConfig.setShowIndex(showIndex);
        foodTableConfig.setShopId(shopId);
        return commonService.searchOneOptional(foodTableConfig);
    }

    /**
     * 查询分店里面的场景，通过场景名称去查询，只查询一个
     *
     * @param shopId
     * @param sceneName
     * @return
     */
    public Optional<Scene> findScene(Long shopId, String sceneName) {
        if (isEmpty(sceneName)) {
            logger.info("scene name is empty , shop id is {}", shopId);
            return Optional.empty();
        }
        Scene scene = new Scene();
        scene.setShopId(shopId);
        scene.setName(sceneName);
        scene.setEntity(true);
        return commonService.searchOneOptional(scene);
    }

    /**
     * 在分店里面去查询菜品
     * 忽略模糊匹配
     *
     * @param shopId
     * @param itemName
     * @return
     */
    public Optional<Item> findItem(Long shopId, String itemName) {
        if (isEmpty(itemName)) {
            logger.info("item name is empty, shopId is {}", shopId);
            return Optional.empty();
        }

        Item item = new Item();
        item.setShopId(shopId);
        item.setName(itemName);
        item.setEntity(true);
        item.setIgnoreLike(true);
        return commonService.searchOneOptional(item);
    }

    /**
     * 导入品类
     *
     * @param srcShopId
     * @param desShopId
     * @throws Exception
     */
    public void importCatalog(Long srcShopId, Long desShopId) throws Exception {
        //将品类查询出来后，再导入
        CommonService commonService = CommonService.getInstance();
        List<Catalog> catalogList = CatalogService.getInstance().findCatalogByShopId(srcShopId);

        for (Catalog srcCatalog : catalogList) {
            Catalog desCatalog = new Catalog();
            BeanUtils.copyProperties(srcCatalog, desCatalog, "sceneJson", "sceneList", "createDate", "createTime");
            desCatalog.setShopId(desShopId);
            desCatalog.setId(null);

            //设备品类对应的场景
            List<NameAndId> desSceneNameAndIdList = copySceneNameAndIdList(srcCatalog.getSceneList(), desShopId);
            desCatalog.getSceneList().addAll(desSceneNameAndIdList);

            commonService.createObject(desCatalog, null, false, null);
        }
    }

    /**
     * 复制场景值
     *
     * @param srcSceneNameAndIdList
     * @param desShopId
     * @return
     */
    public List<NameAndId> copySceneNameAndIdList(List<NameAndId> srcSceneNameAndIdList, Long desShopId) {
        if (isEmpty(srcSceneNameAndIdList)) {
            return new ArrayList<>();
        }

        ArrayList<NameAndId> desNameAndIdList = new ArrayList<>();
        for (NameAndId nameAndId : srcSceneNameAndIdList) {
            String sceneName = nameAndId.getName();
            Optional<Scene> sceneOptional = findScene(desShopId, sceneName);
            if (sceneOptional.isPresent()) {
                Scene desScene = sceneOptional.get();
                NameAndId desNameAndId = new NameAndId();
                desNameAndId.setId(desScene.getId());
                desNameAndId.setName(sceneName);
                desNameAndIdList.add(desNameAndId);
            }
        }

        return desNameAndIdList;
    }

    /**
     * 生成价格区间
     *
     * @param srcPriceConfigList
     * @param desShopId
     * @return
     */
    public List<PriceConfig> copyPriceConfigAndIdList(List<PriceConfig> srcPriceConfigList, Long desShopId) {
        logger.info("copyPriceConfigAndIdList for shop {}", desShopId);
        if (isEmpty(srcPriceConfigList)) {
            logger.info("src price config list is empty");
            return new ArrayList<>();
        }

        ArrayList<PriceConfig> desPriceConfigArrayList = new ArrayList<>();
        for (PriceConfig srcPriceConfig : srcPriceConfigList) {
            PriceConfig desPriceConfig = new PriceConfig();
            BeanUtils.copyProperties(srcPriceConfig, desPriceConfig);
            //修改场景ID
            Optional<Scene> sceneOptional = findScene(desShopId, getSceneName(desPriceConfig));
            if (sceneOptional.isPresent()) {
                Scene scene = sceneOptional.get();
                desPriceConfig.setSceneId(scene.getId());
                desPriceConfigArrayList.add(desPriceConfig);
            } else {
                logger.info("can not find the scene {} in shop {}", desPriceConfig.getSceneName(), desShopId);
            }
        }

        return desPriceConfigArrayList;
    }

    private String getSceneName(PriceConfig priceConfig) {
        try {
            Long sceneId = priceConfig.getSceneId();
            return SceneService.getInstance().findScene(sceneId).getName();
        } catch (Exception e) {
            logger.info("can not find the scene");
            return priceConfig.getSceneName();
        }
    }

    /**
     * 导入套餐
     *
     * @param srcSetMenuOneItemList
     * @param desShopId
     * @return
     */
    public List<SetMenuOneItem> copySetMenuOneItemList(List<SetMenuOneItem> srcSetMenuOneItemList, Long desShopId) throws Exception {
        if (isEmpty(srcSetMenuOneItemList)) {
            logger.info("src set menu item list is empty");
            return new ArrayList<>();
        }

        ArrayList<SetMenuOneItem> desSetMenuOneItemList = new ArrayList<>();
        for (SetMenuOneItem srcSetMenuOneItem : srcSetMenuOneItemList) {
            SetMenuOneItem desSetMenuOneItem = new SetMenuOneItem();
            BeanUtils.copyProperties(srcSetMenuOneItem, desSetMenuOneItem);

            Long itemCatalogId = OrderService.getInstance().generateOrderItemId(desShopId);
            desSetMenuOneItem.setId(itemCatalogId);

            //设置itemId
            for (Item item : getList(srcSetMenuOneItem.getItemList())) {
                Optional<Item> itemOptional = findItem(desShopId, item.getName());
                if (itemOptional.isPresent()) {
                    item.setName(itemOptional.get().getName());
                    item.setName_zh(itemOptional.get().getName_zh());
                    item.setName_en(itemOptional.get().getName_en());
                    item.setId(itemOptional.get().getId());
                    item.setShopId(desShopId);
                } else {
                    logger.info("can not find the item {}, shop is ", item.getName(), desShopId);
                }
            }
        }

        return desSetMenuOneItemList;
    }

    /**
     * 导入菜品
     *
     * @param srcShopId
     * @param desShopId
     * @throws Exception
     */
    public void importItem(Long srcShopId, Long desShopId) throws Exception {
        //并且需要将菜品也导入到对应的分店里面
        CommonService commonService = CommonService.getInstance();
        List<Item> srcItemList = ItemService.getInstance().findItemByShopId(srcShopId);
        List<Scene> sceneList = ShopService.getInstance().findSceneList(desShopId);
        logger.info("src item list size is {}", srcItemList.size());
        for (Item srcItem : srcItemList) {
            Long catalogId = srcItem.getCatalogId();
            Optional<Catalog> catalogOptional = CatalogService.getInstance().findCatalog(catalogId);

            //如果菜品对应的品类已经被删除了，不处理
            if (!catalogOptional.isPresent()) {
                logger.info("catalog deleted");
                continue;
            }

            Item desItem = new Item();
            BeanUtils.copyProperties(srcItem, desItem, "priceConfigJson", "priceConfigList", "saleOut", "leftCount", "leftCountShow", "lockCount", "availableCount");
            desItem.setShopId(desShopId);
            desItem.setId(null);

            //导入到菜里面的场景
            List<NameAndId> itemSceneList = desItem.getSceneList();
            if (isNotEmpty(itemSceneList) && isNotEmpty(sceneList)) {
                for (NameAndId nameAndId : itemSceneList) {
                    for (Scene scene : sceneList) {
                        //场景名字相同(同分店下场景名唯一)，把id更换一下
                        if (equals(nameAndId.getName(),scene.getName())){
                            nameAndId.setId(scene.getId());
                        }
                    }

                }
            }

            //导入价格区间
            List<PriceConfig> desPriceConfigList = copyPriceConfigAndIdList(getList(srcItem.getPriceConfigList()), desShopId);
            desItem.setPriceConfigList(new ArrayList<>());
            desItem.getPriceConfigList().addAll(desPriceConfigList);

            //导入套餐里面的数据
            List<SetMenuOneItem> desSetMenuOneItemList = copySetMenuOneItemList(srcItem.getSetMenuOneItemList(), desShopId);
            if (isNotEmpty(desSetMenuOneItemList)) {
                desItem.setSetMenuOneItemList(new ArrayList<>());
                desItem.getSetMenuOneItemList().addAll(desSetMenuOneItemList);
            }

            if (!isNotEmpty(desItem.getCatalogName())) {
                logger.info("can not find the catalogname of  item {} ", desItem.getName());
                continue;
            }

            Catalog catalog = CatalogService.getInstance().findCatalogByName(desShopId, desItem.getCatalogName());

            if (catalog == null) {
                logger.info("can not find the catalog of  item {}", desItem.getName());
                continue;
            }

            commonService.createObject(desItem);

            //修改所属分类
            //先找到所属分类的名称，然后再设置属性
            CatalogItemMapping catalogItemMapping = new CatalogItemMapping();
            catalogItemMapping.setItemId(srcItem.getId());
            CatalogItemMapping catalogItemMappingInDb = commonService.searchOne(catalogItemMapping);

            //该菜品有映射
            if (catalogItemMappingInDb != null) {
                logger.info("will find the catalog name {}, mapping id {}", catalogItemMappingInDb, catalogItemMappingInDb.getId());
                VerifyUtil.verify(() -> catalog != null, ResponseStatus.SYSTEM_ERROR);
                catalogItemMapping.setCatalogId(catalog.getId());
                catalogItemMapping.setItemId(desItem.getId());
                catalogItemMapping.setOnline(desItem.getOnline());
                catalogItemMapping.setShopId(desShopId);
                catalogItemMapping.setItemName(desItem.getName());
                catalogItemMapping.setItemName_zh(desItem.getName_zh());
                catalogItemMapping.setItemName_en(desItem.getName_en());
                CatalogItemService.getInstantce().createCatalogMapping(catalogItemMapping);
                MappingService.getInstance().createCatalogItemMapping(catalogItemMapping);

                //更新catalog id
                desItem.setCatalogId(catalog.getId());
                commonService.save(desItem);
            } else {
                logger.info("can not find the catalog mapping for item {}", srcItem.getId());
            }
        }
    }


    /**
     * 查询所有的打印标签
     *
     * @param shopId
     * @return
     */
    public List<PrinterLabel> findPrinterLabelList(Long shopId) {
        PrinterLabel printerLabel = new PrinterLabel();
        printerLabel.setShopId(shopId);
        printerLabel.setEntity(true);
        return commonService.searchAll(printerLabel);
    }

    /**
     * 导入打印标签
     *
     * @param srcShopId
     * @param desShopId
     */
    public void importPrintLabel(Long srcShopId, Long desShopId) throws Exception {
        List<PrinterLabel> printerLabelList = findPrinterLabelList(srcShopId);
        if (isEmpty(printerLabelList)) {
            logger.info("src shop {} do not has print label", srcShopId);
            return;
        }

        for (PrinterLabel srcPrinterLabel : printerLabelList) {
            PrinterLabel desPrinterLabel = new PrinterLabel();
            BeanUtils.copyProperties(srcPrinterLabel, desPrinterLabel);
            desPrinterLabel.setShopId(desShopId);
            desPrinterLabel.setId(null);
            commonService.createObject(desPrinterLabel, null, false, null);
        }
    }

    /**
     * 导入餐桌配置
     *
     * @param srcShopId
     * @param desShopId
     * @throws Exception
     */
    public void importFoodTableConfig(Long srcShopId, Long desShopId) throws Exception {
        List<FoodTableConfig> foodTableConfigList = ShopService.getInstance().findFoodTableConfig(srcShopId);

        if (isEmpty(foodTableConfigList)) {
            logger.info("foodTableConfigList is empty");
            return;
        }

        for (FoodTableConfig srcFoodTableConfig : foodTableConfigList) {
            FoodTableConfig desFoodTableConfig = new FoodTableConfig();
            BeanUtils.copyProperties(srcFoodTableConfig, desFoodTableConfig);
            desFoodTableConfig.setShopId(desShopId);
            desFoodTableConfig.setId(null);
            commonService.createObject(desFoodTableConfig, null, false, null);
        }
    }


    /**
     * 导入排队配置
     *
     * @param srcShopId
     * @param desShopId
     * @throws Exception
     */
    public void importLineUpConfig(Long srcShopId, Long desShopId) throws Exception {
        List<LineUpConfig> srcLineUpConfigList = ShopService.getInstance().findEntityListByShopId(srcShopId, LineUpConfig.class);
        if (isEmpty(srcLineUpConfigList)) {
            logger.info("src line up config list is empty ,shop is {}", srcShopId);
            return;
        }

        for (LineUpConfig srcLineUpConfig : srcLineUpConfigList) {
            LineUpConfig desLineUpConfig = copyConfig(srcLineUpConfig, desShopId);
            commonService.createObject(desLineUpConfig);
        }
    }

    /**
     * 导入支付方式
     *
     * @param srcShopId
     * @param desShopId
     */
    public void importPayType(Long srcShopId, Long desShopId) throws Exception {
        List<PayType> payTypeList = ShopService.getInstance().findEntityListByShopId(srcShopId, PayType.class);
        if (isEmpty(payTypeList)) {
            logger.info("src pay type list is empty ,shop is {}", srcShopId);
            return;
        }

        for (PayType srcPayType : payTypeList) {
            PayType payType = new PayType();
            BeanUtils.copyProperties(srcPayType, payType, "id");
            payType.setShopId(desShopId);
            commonService.createObject(payType);
        }

        //再将分店设置成已初始化支付方式
        Shop desShop = ShopService.getInstance().findShopById(desShopId);
        desShop.setInitPayType(true);
        CommonService.getInstance().save(desShop);
    }

    /**
     * 复制配置
     *
     * @param src
     * @param desShopId
     * @param <T>
     * @throws Exception
     */
    public <T extends AbstractEntity> T copyConfig(T src, Long desShopId) throws Exception {
        T des = (T) src.getClass().newInstance();
        BeanUtils.copyProperties(src, des, "id", "shopId");
        des.setId(null);
        Field shopIdField = ClassUtil.getInstance().getField(des.getClass(), "shopId");
        if (shopIdField == null) {
            logger.info("shopId field is empty for class {}", des.getClass().getName());
            return null;
        }

        shopIdField.set(des, desShopId);
        return des;
    }

    /**
     * 导入店铺其它配置
     *
     * @param srcShopId
     * @param desShopId
     */
    public void importShopConfig(Long srcShopId, Long desShopId) throws Exception {
        ShopService shopService = ShopService.getInstance();
        Shop srcShop = shopService.findShopById(srcShopId);
        Shop desShop = shopService.findShopById(desShopId);
        ShopConfig srcShopShopConfig = srcShop.getShopConfig();
        ShopConfig desShopShopConfig = desShop.getShopConfig();
        BeanUtils.copyProperties(srcShopShopConfig, desShopShopConfig);

        //导入商家本身的配置
        //将不同步的数据排除在外
        desShop.setServiceFeePercent(srcShop.getServiceFeePercent());
        desShop.setTakeoutFeePercent(srcShop.getTakeoutFeePercent());
        desShop.setLangInt(srcShop.getLangInt());

        //失效时间
        desShop.setQrCodeOnDeskDisablePayFirst(srcShop.getQrCodeOnDeskDisablePayFirst());
        desShop.setQrCodeOnDeskDisablePayAfter(srcShop.getQrCodeOnDeskDisablePayAfter());
        desShop.setQrCodeDisableAddNewOrderPayFirst(srcShop.getQrCodeDisableAddNewOrderPayFirst());
        desShop.setQrCodeDisableAddNewOrderPayAfter(srcShop.getQrCodeDisableAddNewOrderPayAfter());

        CommonService commonService = CommonService.getInstance();
        commonService.save(desShop);
    }

    /**
     * 删除该分店的品类
     *
     * @param shopId
     */
    public void deleteCatalog(Long shopId) throws Exception {
        shopService.deleteEntity(shopId, Catalog.class);
    }

    /**
     * 删除该分店的商品
     *
     * @param shopId
     */
    public void deleteItem(Long shopId) throws Exception {
        shopService.deleteEntity(shopId, Item.class);
    }

    /**
     * 删除品类与菜品的映射关系
     *
     * @param shopId
     */
    public void deleteCatalogItemMapping(Long shopId) throws Exception {
        shopService.deleteEntity(shopId, CatalogItemMapping.class);
    }

    /**
     * 删除场景
     *
     * @param shopId
     */
    public void deleteScene(Long shopId) throws Exception {
        shopService.deleteEntity(shopId, Scene.class);
    }

    /**
     * 删除打印配置
     *
     * @throws Exception
     */
    public void deletePrinter(Long shopId) throws Exception {
        shopService.deleteEntity(shopId, PrinterLabel.class);
    }

    /**
     * 删除排队配置
     *
     * @param shopId
     * @throws Exception
     */
    public void deleteLineUp(Long shopId) throws Exception {
        shopService.deleteEntity(shopId, LineUpConfig.class);
    }


    /**
     * 删除餐桌
     *
     * @param shopId
     * @throws Exception
     */
    public void deleteFoodTable(Long shopId) throws Exception {
        shopService.deleteEntity(shopId, FoodTable.class);
    }

    /**
     * 删除餐桌配置
     *
     * @param shopId
     * @throws Exception
     */
    public void deleteFoodTableConfig(Long shopId) throws Exception {
        shopService.deleteEntity(shopId, FoodTableConfig.class);
    }

    /**
     * 删除支付方式
     *
     * @param shopId
     * @throws Exception
     */
    public void deletePayType(Long shopId) throws Exception {
        shopService.deleteEntity(shopId, PayType.class);
    }

}
